package com.chy.srb.core.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.chy.srb.core.mapper.DictMapper;
import com.chy.srb.core.pojo.dto.ExcelDictDTO;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 有个很重要的点 DemoDataListener 不能被spring管理，要每次读取excel都要new,然后里面用到spring可以构造方法传进去
 * @Author: chenhy
 * @Date: 2022年01月20日
 */
@Slf4j
@NoArgsConstructor
public class ExcelDictListener implements ReadListener<ExcelDictDTO> {

    private DictMapper dictMapper;

    // 每3000条记录批量存储一次数据
    private static final int BATCH_COUNT = 3000;

    /**
     * 缓存的数据
     */
    private List<ExcelDictDTO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    public ExcelDictListener(DictMapper dictMapper) {
        this.dictMapper = dictMapper;
    }

    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(ExcelDictDTO data, AnalysisContext context) {
        log.info("解析到一条记录: {}", data);
        // 将数据存入数据列表
        cachedDataList.add(data);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if(cachedDataList.size() >= BATCH_COUNT){
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 当最后剩余的数据记录数不足BATCH_COUNT时，我们最终一次性存储剩余数据
        saveData();
        log.info("所有数据解析完成！");
    }

    /**
     * 加上存储数据库
     */
    private void saveData(){
        log.info("{} 条数被存储到数据库......", cachedDataList.size());
        // 调用mapper层的批量save方法：save list对象
        dictMapper.insertBatch(cachedDataList);
        log.info("{} 条数被存储到数据库成功！", cachedDataList.size());
    }
}
